﻿module Utils

type FastArrayBuilder<'a>() =
     inherit System.Collections.Generic.List<'a>()
 
type FastArrayBuilder<'a> with
    member inline arr.Yield(x) = 
        arr.Add(x)
    member inline arr.YieldFrom(xs) = 
        arr.AddRange(xs)
    member inline arr.Run(f) = 
        f()
        arr.ToArray()
    member inline arr.Combine((), f) = 
        f()
    member inline arr.Delay(f) = 
        f
    member inline arr.Zero() = ()
    member inline arr.For(seq, f) = 
        for x in seq do f x
    member inline arr.Using(expr, f) = 
        use e = expr in f e
    member inline arr.While(cond, f) = 
        while cond() do f()
    member inline arr.TryWith(t, f) = 
        try t() with e -> f()
    member inline arr.TryFinally(t, f) = 
        try t() finally f()
 
let inline fastarray<'a> = FastArrayBuilder<'a>()

[<Struct>]
type FastListBuilder<'a> =
    new tl = { tail = tl }
    val mutable tail : 'a list
 
    member inline list.Yield(x) =
        list.tail <- x :: list.tail
    member inline list.YieldFrom(xs) =
        for x in xs do list.tail <- x :: list.tail
    member inline list.Run(f) =
        f()
        List.rev list.tail
    member inline list.Combine((), f) = 
        f()
    member inline list.Delay(f) = 
        f
    member inline list.Zero() = ()
    member inline list.For(seq, f) = 
        for x in seq do f x
    member inline list.Using(expr, f) = 
        use e = expr in f e
    member inline list.While(cond, f) = 
        while cond() do f()
    member inline list.TryWith(t, f) = 
        try t() with e -> f()
    member inline list.TryFinally(t, f) = 
        try t() finally f()
 
let inline fastlist<'a> = FastListBuilder<'a>( [] )

